<?php
/**
 * 众安健康测评结果种算法
 * Created by PhpStorm.
 * User: liao
 * Date: 2016/12/12
 * Time: 16:41
 */

namespace App\Services\Result;

use App\Interf\Resultable;
use Monolog\Logger;
use TestingConfig;
use ParamConfig;
use App\Models\LogHelper;

class ZYhealthResult extends BaseResult implements Resultable
{
    private $answers;
    /**健康概述*/
    private $fatFactorAttrObj;
    /**身体概述*/
    private $bodySummaryAttrObj;


    public function __construct($answersStr = null)
    {
        $this->answers = $this->convertAnswer($answersStr);
        $this->fatFactorAttrObj = $this->configAttrObj(1,'健康概述');
        $this->bodySummaryAttrObj = $this->configAttrObj(2,'健康细节');


    }

    public function result()
    {

        $attrs = [];
        /*健康概述*/
        array_push($attrs,$this->getFatAttr());
        /*健康细节*/
        array_push($attrs,$this->getBodySummaryAttr());


        $data['attrs'] = $attrs;
        $data['chatparam'] = "";
        //图类型常规图
        $data['chatType'] = $this->getChatType();
        return $data;
    }


    /**
     * 健康概述
     */
    protected function getFatAttr(){
        $note = '';
        //测评分数
        $note .= $this->getFatResultFirstNote();
        //健康关注点
        $index = 32;
        $symbol = "|";
        $resultList = ParamConfig::getByTag('ZA.health.focus');
        $otherResult = ParamConfig::getValue('ZA.health.focus.other');
        $note .= $this->getHealthResult($index,$resultList,$otherResult,$symbol);
        $obj = $this->fatFactorAttrObj;
        $obj = $this->compactAttrObj($obj['attr_id'],$obj['title'],$note);
        return $obj;
    }


    /**
     * 健康细节
     */
    protected function getBodySummaryAttr(){
        $note = '';
        //bmi体重指数
        $bmiNote = ParamConfig::getValue("ZA.health.detail.bmi.note");
        $answer34 = $this->getDefaultAnswerObjByIndex(34);
        $bmiNote = str_replace('@34',round($answer34['weight'],2),$bmiNote);
        $note .= $bmiNote;
        $note .= $this->getNote(34);
        //饮食健康指数
        $note .= $this->getNote(37);
        $obj = $this->bodySummaryAttrObj;
        $obj = $this->compactAttrObj($obj['attr_id'],$obj['title'],$note);
        return $obj;
    }







    /**
     * 获取单个问题通过条件判断后最终的结果
     */
    protected function getItemResult($index,$answerWeight){
        $result = '';
        $values = $this->getSingleItemConfig($index);
        if(count($values)>0){
            foreach ($values as $val){
                $expression = $val['key'];
                if($data = $this->getQuestionItemCondResult($expression,$answerWeight)){
                    $result = $val['value'];
                    break;
                }
            }
        }
        return $result;
    }




    /**解析格式 高血压|@5|@5==0 (“高血压”∈$32|@5==0)
     * @param $index
     * @param $resultList
     * @param $otherReult
     * @return string
     */

    //
    protected function getFatWaistResult($index,$resultList,$otherReult,$symbol){
        $answer = $this->getDefaultAnswerObjByIndex($index);
        $answerArr = explode("|||",$answer['answer']);
        $note = "";
        if(count($resultList)>0){
            foreach($resultList as $key => $result){
                $parameters=explode($symbol,$result['key']);
                $weight = $this->getSingleItemVal($parameters[1]);
                $replace = str_replace($parameters[1],$weight,$parameters[2]);
                $val = eval("return $replace;");
                if(in_array($parameters[0],$answerArr) || $val){
                    $note .= $result['value'];
                }
            }
            if(!$note){
                $note .= $otherReult;
            }
        }
        return $note;
    }


    /**解析格式健康概述
     * @param $index
     * @param $resultList
     * @param $otherReult
     * @return string
     */
    protected function getHealthResult($index,$resultList,$otherReult,$symbol){
        $answer = $this->getDefaultAnswerObjByIndex($index);
        $answerArr = explode("|||",$answer['answer']);
        $note = "";
        $many = "";
        $resultArr = [];
        if(count($resultList)>0){
            foreach($resultList as $key => $result){
                $parameters=explode($symbol,$result['key']);
                $weight = $this->getSingleItemVal($parameters[1]);
                $origin = str_replace(" ","",$parameters[1]);
                $replace = str_replace($origin,$weight,$parameters[2]);
                $val = eval("return $replace;");
                if(in_array($parameters[0],$answerArr) || $val){
                    array_push($resultArr,$result['value']);
                    $many .= $result['value'];
                }
            }
            if(count($resultArr)==1){
                $note = $many;
            }elseif(count($resultArr)>1){
                $note = ParamConfig::getValue('ZA.health.focus.many');
            }
            if(!$note){
                $note = $otherReult;
            }

        }
        return $note;
    }




    //一天食谱样式
    protected function formateRecipeContent($arr,$num){
        $title = ParamConfig::getValue('ZA.health.recipe.meals.span');
        $title = str_replace('{num}',$num,$title);
        $breakfast = $arr['breakfast'];
        $lunch = $arr['lunch'];
        $supper = $arr['super'];
        //早餐
        $bstart = 2 * $num - 2;
        //数组截取
        $dataBreakfast = array_slice($breakfast, $bstart, 2, true);
        $breakfast_Htmls = "";
        if(count($dataBreakfast)>0) {
            $breakfastHtml = $this->Onemeals($dataBreakfast);
            $breakfastHtmls = ParamConfig::getValue("ZA.health.recipe.meals.breakfast.div");
            $breakfast_Htmls = str_replace("{content}", $breakfastHtml, $breakfastHtmls);
        }
        $title .=$breakfast_Htmls;
        //午餐
        $lstart = 3 * $num - 3;
        //数组截取
        $dataLunch = array_slice($lunch, $lstart, 3, true);
        $lunch_Htmls="";
        if(count($dataLunch)>0){
            $lunchHtml =  $this->Onemeals($dataLunch);
            $lunchHtmls = ParamConfig::getValue("ZA.health.recipe.meals.lunch.div");
            $lunch_Htmls = str_replace("{content}", $lunchHtml, $lunchHtmls);
        }
        $title .=$lunch_Htmls;
        //晚餐
        $sstart = 3 * $num - 3;
        //数组截取
        $dataSupper = array_slice($supper, $sstart, 3, true);
        $supper_Htmls ="";
        if(count($dataSupper)>0){
            $supperHtml =  $this->Onemeals($dataSupper);
            $supperHtmls = ParamConfig::getValue("ZA.health.recipe.meals.supper.div");
            $supper_Htmls = str_replace("{content}", $supperHtml, $supperHtmls);
        }
        $title .=$supper_Htmls;
        $recipeConten = ParamConfig::getValue("ZA.health.recipe.div");
        $recipeConten = str_replace("{content}", $title, $recipeConten);
        return $recipeConten;
    }

    /**
     * 一餐数据
     */
    protected function Onemeals($data){
        $breakfasts = "";
        foreach ($data as $v) {
            $maininners = "";
            if(count($v['main'])>0){
                foreach($v['main'] as $value){
                    $maininner = ParamConfig::getValue('ZA.health.recipe.meals.inner.span');
                    $maininner = str_replace('{name}', $value['name'], $maininner);
                    $maininners .= $maininner;
                }
                $maindiv = ParamConfig::getValue('ZA.health.recipe.meals.inner.div');
                $maindiv = str_replace('{name}', $v['name'], $maindiv);
                $maindiv = str_replace('{content}', $maininners, $maindiv);
            }
            $accessoriess="";
            if(count($v['Accessories'])>0){
                foreach($v['Accessories'] as $value){
                    $accessoriesspan = ParamConfig::getValue('ZA.health.recipe.meals.inner.span');
                    $accessoriesspan = str_replace('{name}', $value['name'], $accessoriesspan);
                    $accessoriess .= $accessoriesspan;
                }
                $accessoriesp = ParamConfig::getValue('ZA.health.recipe.meals.accessories.p');
                $accessoriesp = str_replace('{content}',$accessoriess, $accessoriesp);
                $maindiv .= $accessoriesp;
            }
            $breakfast = ParamConfig::getValue('ZA.health.recipe.meals.breakfast.li');
            $breakfast = str_replace('{imgurl}',$v['icon'], $breakfast);
            $breakfast = str_replace('{content}',$maindiv, $breakfast);
            $breakfasts .=$breakfast;
        }
        return $breakfasts;
    }


    /**返回食谱
     * @return array|string
     */
    protected function getRecipe(){
        $resultList = ParamConfig::getByTag('ZA.health.recipe');
        $recipe = "";
        if(count($resultList)>0){
            foreach($resultList as $key => $result){
                $parameters=explode("%",$result['key']);
                if(count($parameters) >= 3){
                    $weight = $this->getSingleItemVal($parameters[1]);
                    $origin = str_replace(" ","",$parameters[1]);
                    $replace = str_replace($origin,$weight,$parameters[2]);
                    $val = eval("return $replace;");
                    $answerArr = explode('|',$parameters[0]);
                    $answer = $this->getSingleItemVal($answerArr[1]);
                    $answerArrs = explode("!",$answerArr[0]);
                    $symbol = $parameters[3];
                    $tag = "";
                    $answers = explode("|||",$answer);
                    foreach($answers as $v){
                        if($symbol == "||"){
                            if(in_array($v,$answerArrs) || $val){
                                $tag = $result['value'];
                                break;
                            }
                        }else{
                            if($val && strpos($parameters[2],">=2")){
                                $special = explode("?",$answerArrs[0]);
                                if(in_array($special[0],$answers) && in_array($special[1],$answers)){
                                    $tag = $result['value'];
                                    break;
                                }
                            }elseif(in_array($v,$answerArrs) && $val){
                                $tag = $result['value'];
                                break;
                            }
                        }
                    }
                    if($tag){
                        $recipe = strip_tags($tag);
                        break;
                    }
                }
            }
        }
        if(!$recipe){
            $recipe = strip_tags(ParamConfig::getValue('ZA.health.recipe.other'));
        }
        return $recipe;
    }


    /**
     * @param $index
     * @param null $type
     * @return string
     */
    protected function getNote($index,$type=null){
        $answer34 = $this->getDefaultAnswerObjByIndex($index);
        $note = '';
        $bmiAll = ParamConfig::getByTag("ZA.health.result.".$index);
        $str = "@".$index;
        if(count($bmiAll)>0) {
            foreach ($bmiAll as $result) {
                $replace = str_replace($str, round($answer34['weight'], 2), $result['key']);
                $val = eval("return $replace;");
                if($val){
                    if(!$type){
                        $note .= $result['value'];
                        break;
                    }else{
                        $note['note'] =$result['value'];
                        $note['express']=$result['key'];
                    }

                 }
            }

        }
        return $note;
    }





    /**
     * 获取健康概述第一个结论部分
     */
    protected function getFatResultFirstNote(){
        $note = ParamConfig::getValue('ZA.health.result.first.note');
        $answer36 = $this->getDefaultAnswerObjByIndex(36);
        $weight = intval($answer36['weight']);
        if($weight >= 100){
            $weight = 99;
        }elseif($weight <= 0){
            $weight = 1;
        }
        $note = str_replace('$z',$weight,$note);
        $dis = ParamConfig::getByTag('ZA.health.result.36');
        if(count($dis)>0){
            foreach ($dis as $result){
                $key = $result['key'];
                //现替换表达式中的值 ，表达式原型为@3==0 && @24==2
                $key = str_replace('$z',$weight,$key);
                //在将表达式赋值为val变量，并通过eval函数进行运算得出val的值
                $val = '$val='.$key.';';
                eval($val);
                if($val){
                    $note = str_replace('xxx',$result['value'],$note);
                    break;
                }
            }
        }
        return $note;
    }

    protected function compactAttrObj($id,$title,$note,$extra=''){
        return [
            'attr_id' => $id,
            'title' => $title,
            'note' => $note,
            'extra' =>$extra
        ];
    }

    protected function getDefaultAnswerObjByIndex($index){
        $obj = [];
        foreach ($this->answers as $answer){
            if($index == $answer['index']){
                $obj = $answer;
                break;
            }
        }
        return $obj;
    }


    /**
     * 组装结果集
     */
    protected function compactResults($itemList){
        $results = [];
        if(count($itemList)>0){
            foreach ($itemList as $item){
                if($result = $this->getItemResult($item['index'],$item['value'])){
                    array_push($results,$result);
                }
            }
        }
        return $results;
    }






    /**
     * 获取单个题目对应的条件判断值
     */
    protected function getQuestionItemCondResult($expression,$originVal){
        $expression = $expression.'?1:0;';
        $result = $this->compactExpress($expression,$originVal);
        return $result;
    }

    /**
     * 组装表达式,这里充分的利用eval函数可以计算的功能
     * @param string $expression 原始表达式
     * @param string $orgVal 原始值
     * @return string
     */
    protected function compactExpress($expression, $orgVal){
        $val = '$val=$orgVal;$val='.$expression;
        eval($val);
        return $val;
    }



    //获取中间对应的权重或者值
    private function getSingleItemVal($parame){
        $parameArr = explode(" ",$parame);
        $answer = $this->getAnswerObjByIndex($this->answers,$parameArr[1]);
        $operateData =  '';
        if($parameArr[0] == '#'){
            //这里因为$会被转义，所以采用#
            $operateData = $answer['answer'];
        }else if($parameArr[0] == '@'){
            $operateData = $answer['weight'];
        }
        return $operateData;
    }



    /**将answer转换为数组
     * @param $answerStr
     * @return array
     */
    protected function convertAnswer($answerStr){
        LogHelper::log('FINAL ANSWER STR============>');
        LogHelper::log($answerStr);
        $answers = [];
        $answerArr = explode('##',$answerStr);
        if(count($answerArr)>0){
            foreach ($answerArr as $answer){
                $singleArr = explode(':',$answer);
                if(count($singleArr)>0){
                    $obj['index'] = $singleArr[0];
                    $obj['weight'] = $singleArr[1];
                    $obj['answer'] = $singleArr[2];
                    array_push($answers,$obj);
                }
            }
        }
        return $answers;
    }


}